Parity#402
Draft
thorrester wants to merge 2 commits into
Draft
Conversation
Dependency Review✅ No vulnerabilities or license issues found.Scanned Manifest Filespy-opsml/uv.lock
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request
Short Summary
Adds a fluent experiment API —
opsml.log_metric(),opsml.log_param(), and friends — backed by a process-globalActiveStack<Experiment>in Rust, with per-frameworklog_modelshortcuts (sklearn_log_model,torch_log_model, etc.) that register aModelCardin one call. Also refactors the trace dashboard filter state from flat fields into a composableFilterClausetree, dropping N parallel facet API calls down to 2.Context
Fluent experiment API
Previously, logging to an experiment required a captured reference:
exp.log_metric(...). This PR adds free functions that resolve the current experiment from a process-global stack pushed/popped byExperiment.__enter__/__exit__:Before:
After:
The stack lives in
crates/opsml_experiment/src/active.rsas aMutex<Vec<Py<Experiment>>>. Single-threaded only — the comment is explicit that concurrent experiments must use the explicit form.active_experiment()exposes the current experiment for callers that need it directly.Flavor
log_modelfunctionsEach supported framework now has a
{framework}_log_model(model, *, name, space=None, ...)free function inpy-opsml/src/flavors.rs. Whenspaceis omitted, it reads the active experiment's space — soopsml.sklearn.log_model(...)inside awith start_experiment(...)block just works. Returns a registeredModelCard.ModelInterfacesubclass fixPyO3 requires
__new__and__init__to be separate for Python subclassing to work.ModelInterfacepreviously used#[new]with a full constructor signature, which broke subclasses that pass extra kwargs. Split into__new__(*args, **kwargs) -> Self::default()+__init__(self, model=None, ...)that does the real initialization. The stubs were updated to reflect the**kwargsin__init__and the explicit__new__signature.Trace filter refactor
The
TraceDashboardwas managing filter state as flat struct fields (service_name,service_namespace,service_version,service_instance_id,status_code,has_errors,attribute_filters). Every filter change fired up to 5 parallelgetServerTraceFacetscalls (one per field cleared to compute "what else matches"). This PR replaces the flat shape with a composableFilterClausetree inclause.ts:Down to 2 calls.
clause.ts(~370 lines) covers builders (serviceClause,statusCodeClause,attrClause,durationMinClause, etc.), combinators (andClause,addToClause,replaceClauseDimension,removeClauseDimension), and anActiveFiltertype for chip display. Also addsvalidation.tsfor trace span input validation andwaterfall.tsfor the depth-first span sort that was previously inlined inTraceWaterfall.svelte.SvelteMap/SvelteSetreplaces bareMap/Setfor reactive correctness.Dev tooling
mise.tomlgainsdev:e2e:*tasks for a full E2E harness against a live Scouter instance (expects a sibling../scoutercheckout orSCOUTER_DIRoverride). Python formatter consolidated fromisort + black + rufftoruff format + ruff check --fix.pylintdropped in favor ofty. BothMakefileandpy-opsml/makefileremoved.crates/opsml_experiment/src/active.rsActiveStack<Experiment>— push/pop/currentcrates/opsml_experiment/src/fluent.rslog_metric,log_param,log_artifact,log_figure,set_tag,active_experimentcrates/opsml_experiment/src/experiment.rs__enter__/__exit__push/pop the stack; addslog_param/log_params/set_tag/set_tagsaliasespy-opsml/src/flavors.rslog_modelfree functions, space resolution from active experimentcrates/opsml_interfaces/src/model/base/interface.rs#[new]+__init__for PyO3 subclass compatibilitycrates/opsml_server/opsml_ui/src/lib/components/trace/clause.tsFilterClausealgebra replacing flat filter fieldscrates/opsml_server/opsml_ui/src/lib/components/trace/TraceDashboard.sveltecrates/opsml_server/opsml_ui/src/lib/components/trace/waterfall.tscrates/opsml_server/opsml_ui/src/lib/components/trace/validation.tspy-opsml/python/opsml/__init__.pylog_modelwrapperspy-opsml/python/opsml/{sklearn,torch,...}/py-opsml/tests/test_fluent.pypy-opsml/tests/test_fluent_flavors.pymise.tomlMakefile,py-opsml/makefileIs this a Breaking Change?
No. All Python additions are new exports; existing
Experimentmethod signatures are unchanged. The trace filter refactor is internal UI state — the API server routes and response contracts are unmodified.ModelInterface.__new__now accepts*args/**kwargs, which is strictly more permissive for Python subclasses.